from socket import *
import struct
import sys


# Open a UDP socket, bind it to a port and select a multicast group
def mcast_recv_socket(group, port):
    
    # Create a socket
    s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
    #
    # Allow multiple copies of this program on one machine
    # (not strictly needed)
    s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    if hasattr(socket, "SO_REUSEPORT"):
        # Some systems don't support SO_REUSEPORT
        s.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
#    try :
#        s.setsockopt(SOL_IP, IP_MULTICAST_LOOP, 1)
#    except: pass
    #
    # Bind it to the port
    s.bind(('', port))
    #
    # Look up multicast group address in name server
    # (doesn't hurt if it is already in ddd.ddd.ddd.ddd format)
    group = gethostbyname(group)

    ifaddr = INADDR_ANY
    mreq = struct.pack('4sl', inet_aton(group), htonl(ifaddr)) 
    #
    # Add group membership
    try:
        s.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq)
    except: pass
    #
    return s


# Open a UDP socket, and join to a multicast group
def mcast_send_socket(ttl=20):
    
    s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
    ttl = struct.pack('b', ttl)               # Time-to-live
    s.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL, ttl)
    
    return s


def get_ip_address(ifname='eth0'):
    
    addr = [ip for ip in gethostbyname_ex(gethostname())[2] if not ip.startswith("127.")][0]
    
#    if sys.platform[:3] == 'win' :
#        return gethostbyname(gethostname())
#    else:
#        from fcntl import ioctl
#        s = socket(AF_INET, SOCK_DGRAM)
#        addr = None
#        for ifname in ('eth0', 'wlan0', 'lo', 'en0', 'en1') :
#            try :
#                addr = inet_ntoa(ioctl(
#                    s.fileno(),
#                    0x8915, # SIOCGIFADDR
#                    struct.pack('256s', ifname[:15])
#                )[20:24])
#                break
#            except: continue
#        
#        s.close()
        
    return addr
    

if __name__ == "__main__":
    
    import threading
    import time
    import LogPrint
    import random
    
    print 'ip:', get_ip_address()
    
    addr = ('225.21.21.25', 8011)
    def send(msg):
        pause = random.randint(1, 10)
        time.sleep(pause)
        
        sender = mcast_send_socket(2)
        sender.sendto(msg, addr)
        LogPrint.debug_print('send : %s,\tpause:%d' % (msg, pause))
        sender.close()
        LogPrint.debug_print('socket closing')
        
    
    def receive():
        
        data = ''
        s = mcast_recv_socket("225.21.21.25", 8011)
        while data != 'q-' :
            data, addr = s.recvfrom(1024)  
            print 'content: %s\nfrom: %s' % (data, str(addr))
        
        s.close()
        LogPrint.debug_print("receive leaving")
    
    t0 = threading.Thread(target=receive)
    t0.setDaemon(True)
    t1 = threading.Thread(target=send, args=('hello!',))
    t2 = threading.Thread(target=send, args=('hello!',))
    t3 = threading.Thread(target=send, args=('q-',))
    
    t0.start()
    t1.start()
    t2.start()
    t3.start()
    
    t0.join()
    